//
//  HMRefreshControl.swift
//  WeiBo14
//
//  Created by HM on 16/3/9.
//  Copyright © 2016年 HM. All rights reserved.
//

import UIKit

/// 刷新控件的三种状态
///
/// - Normal:     默认
/// - Pulling:    松手就可以去刷新的状态
/// - Refreshing: 正在刷新的状态
enum HMRefreshControlState: Int {
    case Normal = 0, Pulling, Refreshing
}


// 当前刷新控件的高度
private let HMRefreshControlH: CGFloat = 50

class HMRefreshControl: UIControl {
    
    // 代表当前控件的状态
    var refreshState: HMRefreshControlState = .Normal {
        didSet{
            switch refreshState {
            case .Pulling:
                

                print("进入松手就刷新状态")
                // 1. 文字改变
                messageLabel.text = "放开起飞"
                
                UIView.animateWithDuration(0.25, animations: { () -> Void in
                    // 2. 箭头调头
                    self.arrowImage.transform = CGAffineTransformMakeRotation(CGFloat(M_PI))
                })
            
            case .Normal:
                print("默认状态")
                // 0. 箭头显示,菊花隐藏
                arrowImage.hidden = false
                indicatorView.stopAnimating()
                // 1. 文字改变
                messageLabel.text = "下拉起飞"
                UIView.animateWithDuration(0.25, animations: { () -> Void in
                    // 2. 箭头调头
                    self.arrowImage.transform = CGAffineTransformIdentity
                })
                
                if oldValue == .Refreshing {
                    // 判断上一次状态是刷新中状态,那么进入到Normal状态就需要去减去InsetTop
                    UIView.animateWithDuration(0.25, animations: { () -> Void in
                        self.scrollView?.contentInset.top -= HMRefreshControlH
                    })
                }
            case .Refreshing:
                print("刷新中状态")
                // 1. 隐藏箭头
                arrowImage.hidden = true
                // 2. 显示菊花转
                indicatorView.startAnimating()
                // 3. 更改文字
                messageLabel.text = "正在起飞"
                
                // 4. 更改 contentInsetTop,让其停留在界面上
                UIView.animateWithDuration(0.25, animations: { () -> Void in
                    self.scrollView?.contentInset.top += HMRefreshControlH
                })
                sendActionsForControlEvents(UIControlEvents.ValueChanged)
            }
        }
    }
    
    // 当前控件观察的对象 (一般来说都是父控件)
    weak var scrollView: UIScrollView?

    override init(frame: CGRect) {
        super.init(frame: frame)
        
        setupUI()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // 设置视图
    private func setupUI(){
        // 设置其大小
        frame.size = CGSize(width: SCREENW, height: HMRefreshControlH)
        frame.origin.y = -HMRefreshControlH
        
        // 添加子控件
        addSubview(arrowImage)
        addSubview(indicatorView)
        addSubview(messageLabel)
        // 添加约束
        
        arrowImage.snp_makeConstraints { (make) -> Void in
            make.centerY.equalTo(self)
            make.centerX.equalTo(self).offset(-30)
        }
        
        indicatorView.snp_makeConstraints { (make) -> Void in
            make.center.equalTo(arrowImage)
        }
        
        messageLabel.snp_makeConstraints { (make) -> Void in
            make.leading.equalTo(arrowImage.snp_trailing)
            make.centerY.equalTo(arrowImage)
        }
        
    }
    
    // 结束刷新要调用的方法
    func endRefreshing(){
        // ???????????
        refreshState = .Normal

    }
    
    
    // 将要移动到某个父控件上的时候,就会调用该方法
    override func willMoveToSuperview(newSuperview: UIView?) {
        super.willMoveToSuperview(newSuperview)
        print(newSuperview)
        
        if let scrollView = newSuperview as? UIScrollView {
            // 监听滚动
            // 要监听谁,就用谁去调用 addObserver 的方法 --> 给要监听的对象添加一个观察者
            scrollView.addObserver(self, forKeyPath: "contentOffset", options: [.Old,.New], context: nil)
            self.scrollView = scrollView
            // 设置当前控件的宽度为其父控件的宽度
            self.frame.size.width = scrollView.frame.width
        }
    }
    
    // 当当前控件观察的对象身上某个属性发生改变的时候会调用
    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        // print("change:\(change);contentInset.top=\(scrollView?.contentInset.top)")
        
        // -114 怎么计算出来的??? -64-当前控件的高度
        let contentInsetTop = scrollView!.contentInset.top
        let contentOffsetY = scrollView!.contentOffset.y
        // 当前刷新控件在这种情况下完全显示出来的值
        let conditionValue = -contentInsetTop - HMRefreshControlH
        
        // dragging 是代表是否在被用户拖动
        if scrollView!.dragging {
            // 如果当前的contentOffset.y小于或者等于conditionValue,那么就代表当前控件完全显示出来
            // 如果上面条件满足,并且当前状态是默认状态,那么就进入到 松手就刷新的状态(.Pulling)
            if contentOffsetY <= conditionValue && refreshState == .Normal {
                refreshState = .Pulling
                print("松手就刷新")
            }else if refreshState == .Pulling && contentOffsetY > conditionValue{
                // 如果当前是松手就刷新状态,用户不松,把控件推回去.那么就设置当前状态为 .Normal
                // 在这儿要设置成 normal
                refreshState = .Normal
                print("进入默认状态")
            }
        }else{
            // 如果用户松手并且如果当前状态是Pulling状态,就进入到 Refreshing状态
            if refreshState == .Pulling {
                refreshState = .Refreshing
                print("进入刷新状态")
            }
        }
    }
    
    deinit {
        scrollView?.removeObserver(self, forKeyPath: "contentOffset")
    }
    
    
    // MARK: - 懒加载控件
    
    private lazy var indicatorView: UIActivityIndicatorView = {
        let indicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.White)
        return indicatorView
    }()
    
    // 箭头
    private lazy var arrowImage: UIImageView = UIImageView(image: UIImage(named: "tableview_pull_refresh"))
    
    private lazy var messageLabel: UILabel = {
        let label = UILabel(textColor: UIColor.lightGrayColor(), fontSize: 12)
        label.text = "下拉起飞"
        return label
    }()


}
